package controller

import (
	"background/utils"
	"container/list"
	"encoding/xml"
	"fmt"
	"io"
	"log"

	"github.com/gin-gonic/gin"
)

type OpenApiController struct {
}
type DiffRequest struct {
	Origin string `json:"origin"`
	New    string `json:"new"`
}

//from: 发送人邮箱
//to:接收邮件,可以是"290198252@qq.com;29019822@qq.com;2901982@qq.com" 邮箱之间用分号隔开
//template:模板名字
//content :网页模板的参数 key-value结构
//temp_data 模板内具体要替换的变量名字  Key-value结构
//generate  是否生成静态html
func (this *OpenApiController) OndiffCallback(c *gin.Context) {
	var req DiffRequest
	var resp RespBase
	defer func() {
		c.JSON(200, resp)
	}()

	e := c.Bind(&req)
	if e != nil {
		log.Println(e.Error())
		resp.Msg = "ParaErr"
		return
	}

	resp.Msg = "OK"
}

type ReqDDL struct {
	Data string `json:"data"`
}

func (this *OpenApiController) DDL2ORM(c *gin.Context) {
	var req ReqDDL
	resp := RespBase{
		Msg: "err",
	}
	defer func() {
		c.JSON(200, resp)
	}()

	e := c.Bind(&req)
	if e != nil {
		log.Println(e.Error())
		resp.Msg = "ParaErr"
		return
	}
	tbname, fields := utils.DDL2Field(req.Data)
	log.Print(tbname, fields)
	gocode := utils.CreateGoStruct(tbname,fields)
	resp.Data = gocode
	resp.Msg = "OK"
	resp.Status = 0
}


func getAttr(name string, attr []xml.Attr) string {
    for _, a := range attr {
        if a.Name.Local == name {
            return a.Value
        }
    }
    return ""
}

type Widget struct{
	Name string
	Class string
	Parent  *Widget
	Childs  list.List
}

func RangeWidget(p *Widget ) string{
	if nil == p{
		return ""
	}
	ret := ""
	parent := ""
	tmp := p
	for ;tmp != nil;tmp = tmp.Parent{
		parent = tmp.Class + "#" + tmp.Name +  " " + parent
	}
	ret +=  parent +  ` \r\n{\r\n}\r\n`

	if(p.Childs.Len() > 0){
		wid := p.Childs.Front()
		for ;wid != nil;wid = wid.Next(){
			tmp := wid.Value.(*Widget)
			ret += RangeWidget(tmp)
		}	
	}
	return ret
}

type Controller struct{
	Type string  
	Name string
	Parent *Controller
	Childs  list.List	
}

func GetUifrom(path io.Reader) string{
	list := list.List{}

	decoder := xml.NewDecoder(path)
	for {
		token, _ := decoder.Token()
		if token == nil {
			break
		}
		switch startElement := token.(type) {
			case xml.StartElement:
				log.Print(0,startElement.Name)
				if(list.Len()  == 0){
					ins := new(Controller)
					ins.Name = getAttr("name",startElement.Attr)
					log.Print(ins.Name)
					ins.Parent = nil
					list.PushBack(ins)
				}else{
					ins := new(Controller)
					ins.Type = startElement.Name.Local
					ins.Name = getAttr("name",startElement.Attr)
					log.Print(ins.Name)
					ins.Parent = list.Back().Value.(*Controller)
					list.Back().Value.(*Widget).Childs.PushBack(ins)
					list.PushBack(ins)
				}
				break
			case xml.EndElement:
				log.Print(1,startElement.Name)
				if(startElement.Name.Local == "widget"){
					if(list.Len() > 0){
						if(list.Back().Value.(*Widget).Parent != nil){
							list.Remove(list.Back())
						}
					}
				}
				break
		}
	}
	p := list.Back().Value.(*Widget)
	ret := RangeWidget(p)
	log.Print(ret)
	return ret
}


func (this *OpenApiController) DDL2Markdown(c *gin.Context) {
	var req ReqDDL
	resp := RespBase{
		Msg: "err",
	}
	defer func() {
		c.JSON(200, resp)
	}()

	e := c.Bind(&req)
	if e != nil {
		log.Println(e.Error())
		resp.Msg = "ParaErr"
		return
	}
	tbname, fields := utils.DDL2Field(req.Data)
	log.Print(tbname, fields)
	gocode := utils.CreateMarkdownTable(tbname,fields)
	resp.Data = gocode
	resp.Msg = "OK"
	resp.Status = 0
}


func (this *OpenApiController) UI2CSS(c *gin.Context) {

	f, err := c.FormFile("ui")  //根据name返回给第一个文件
	if err != nil {
		c.String(200,"上传文件错误")
		return
	}
	file,e := f.Open()
	if nil != e{
		c.String(200,"上传文件错误")
		return
	}
	ret := GetUifrom(file)
	c.String(200,ret)
}


func GetXMLNode(xmltype string ) string{
	return string("m_") +  utils.ToSnakeString(xmltype) + "_"
}

func GetXmlController(path io.Reader) string{
	list := list.List{}
	maps := map[string]int{}
	ret := ""

	decoder := xml.NewDecoder(path)
	for {
		token, _ := decoder.Token()
		if token == nil {
			break
		}
		switch startElement := token.(type) {
			case xml.StartElement:
				if(list.Len()  == 0){
					ins := new(Controller)
					ins.Type = startElement.Name.Local
					ins.Name = getAttr("name",startElement.Attr)
					ins.Parent = nil
					list.PushBack(ins)
				}else{
					ins := new(Controller)
					ins.Type = startElement.Name.Local
					ins.Name = getAttr("name",startElement.Attr)
					ins.Parent = list.Back().Value.(*Controller)
					list.Back().Value.(*Controller).Childs.PushBack(ins)
					list.PushBack(ins)
				}
				break
			case xml.EndElement:
				break
		}
	}
	begin := list.Front()
	first := true
	fatherType := begin.Value.(*Controller).Type 
	log.Print(begin.Value.(*Controller).Type)
	
	for begin.Next() != nil{
		if begin.Value.(*Controller).Name != ""{
			if first{
				first = false
			}else{
				if _,ok := maps[begin.Value.(*Controller).Type] ;ok{
					 maps[begin.Value.(*Controller).Type]++
				}else{
					 maps[begin.Value.(*Controller).Type] = 1
				}
					
				ret += fmt.Sprintf("ui::%s * m_%s_%d;\r\n",
				begin.Value.(*Controller).Type,
				utils.ToSnakeString(begin.Value.(*Controller).Type),
				maps[begin.Value.(*Controller).Type])
			}
		}
		begin = begin.Next()
	}
	
	ret+="\r\n\r\n"

	begin = list.Front()
	first = true
	for k := range maps {
		delete(maps, k)
	}
	
	for begin.Next() != nil{
		if begin.Value.(*Controller).Name != ""{
			if first{
				first = false
			}else{
				if _,ok := maps[begin.Value.(*Controller).Type] ;ok{
					 maps[begin.Value.(*Controller).Type]++
				}else{
					 maps[begin.Value.(*Controller).Type] = 1
				}
				if(fatherType == "Window"){
					ret += fmt.Sprintf("ui::%s * m_%s_%d = dynamic_cast<ui::%s*>(FindControl(L\"%s\"));\r\n",
					begin.Value.(*Controller).Type,
					utils.ToSnakeString(begin.Value.(*Controller).Type),
					maps[begin.Value.(*Controller).Type],
					begin.Value.(*Controller).Type,
					begin.Value.(*Controller).Name)
				}
				if(fatherType == "ChildBox"){
					ret += fmt.Sprintf("ui::%s * m_%s_%d = dynamic_cast<ui::%s*>(FindSubControl(L\"%s\"));\r\n",
					begin.Value.(*Controller).Type,
					utils.ToSnakeString(begin.Value.(*Controller).Type),
					maps[begin.Value.(*Controller).Type],
					begin.Value.(*Controller).Type,
					begin.Value.(*Controller).Name)
				}
			}
		}
		begin = begin.Next()
	}
	
	return ret
}

func (this *OpenApiController) DuilibXml2Cpp(c *gin.Context) {
	f, err := c.FormFile("xml")  //根据name返回给第一个文件
	if err != nil {
		c.String(200,"上传文件错误")
		return
	}
	file,e := f.Open()
	if nil != e{
		c.String(200,"上传文件错误")
		return
	}
	ret := GetXmlController(file)
	log.Print(ret)
	c.String(200,ret)
}


